package cn.com.bluemoon.daps.model.entity;

import cn.com.bluemoon.daps.common.domain.BaseModel;
import cn.com.bluemoon.daps.common.enums.DatabaseType;
import cn.com.bluemoon.daps.common.sql.IDbDataSource;
import cn.com.bluemoon.daps.common.validation.illegal.IllegalChar;
import cn.com.bluemoon.daps.model.dto.DapModelVersionInter;
import cn.com.bluemoon.daps.model.dto.DevImportCheck;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Objects;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * <p>
 * 模型下属表索引信息表
 * </p>
 *
 * @author admin
 * @since 2020-08-07
 */
@Data
@Accessors
@ApiModel(value = "DapDataModelSubordinateKey", description = "模型下属表索引信息表")
public class DapDataModelSubordinateKey extends BaseModel<DapDataModelSubordinateKey>
        implements DapModelVersionInter, IDbDataSource {
    public static final LinkedHashMap<String, String> includeFieldAndDescMap = new LinkedHashMap<String, String>() {{
        put("keyChinName", "索引中文名");
        put("keyMethod", "索引方法");
        put("keyName", "索引名");
        put("keyType", "索引类型");
        put("fieldNames", "字段名");
        put("tableName", "表英文名");
    }};
    /**
     * 索引方法+类型默认值
     */
    public static final Integer KEY_TYPE_DEFAULT_KEY = 2;
    public static final Integer KEY_METHOD_DEFAULT_KEY = 1;
    public static final String INDEX_FIELDIDS_CHAR = ",";
    public static final String[] includeFields = new String[]{"keyChinName", "keyMethod", "keyName", "keyType", "fieldNames", "tableName"};
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "索引中文名")
    @Size(max = 1024, message = "索引中文名不可以大于{max}")
    @Size(max = 1024, message = "索引中文名不可以大于{max}", groups = DevImportCheck.class)
    private String keyChinName;
    @ApiModelProperty(value = "索引方法, 1:表示为空 2:btree, 3:hash；pgsql中只允许为btree")
    @NotNull(message = "索引类型不允许为空")
    @NotNull(message = "索引类型不允许为空", groups = DevImportCheck.class)
    private Integer keyMethod = KEY_METHOD_DEFAULT_KEY;
    @ApiModelProperty(value = "索引名")
    @Size(max = 64, message = "索引名不可以大于{max}")
    @IllegalChar(name = "keyName", message = "索引中存在非法字符")
    // @NoSqlKeyword(name = "keyName", message = "索引名不可为关键字")
    @Size(max = 64, message = "索引名不可以大于{max}")
    @NotNull(message = "索引名不可为空", groups = DevImportCheck.class)
    private String keyName;
    @ApiModelProperty(value = "索引类型, 1:表示为空, 2:normal, 3:unique, 4:fulltext, 5:spatial")
    @NotNull(message = "索引类型不允许为空")
    @NotNull(message = "索引类型不允许为空", groups = DevImportCheck.class)
    private Integer keyType = KEY_TYPE_DEFAULT_KEY;

    @ApiModelProperty(value = "模型下属表id")
    @NotNull(message = "模型下属表id不允许为空")
    private String modelTableId;

    @ApiModelProperty(value = "模型id")
    @NotNull(message = "模型id不允许为空")
    private String dataModelId;

    @ApiModelProperty(value = "对应模型属下表的字段ids,多个id用英文逗号隔开")
    @NotNull(message = "字段不允许为空")
    private String fieldIds;

    @ApiModelProperty(value = "对应模型属下表的字段名,多个name用英文逗号隔开")
    @TableField(exist = false)
    @NotNull(message = "索引字段列表不允许为空", groups = DevImportCheck.class)
    @JsonIgnore
    private String fieldNames;

    @ApiModelProperty(value = "对应模型属下表的字段名,多个name的长度（针对前缀索引）用英文逗号隔开")
    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private String fieldNameSubParts;

    @ApiModelProperty(value = "已发布版本的数据，记录模型下最新的唯一id，比如：最新表id,最新索引id ")
    private String pId;

    @ApiModelProperty(value = "标记当前数据是否为模型最新数据，null/0 为已发布数据、1为该模型下的最新数据")
    private Integer dataNewest;

    @ApiModelProperty(value = "记录ddl操作的最新时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime ddlChangeTime;

    /**
     * 用于查询字段+表名的对象
     */
    @ApiModelProperty(value = "表英文名称", hidden = true)
    @TableField(exist = false)
    private String tableName;
    @ApiModelProperty(value = "存储索引中的字段名信息", hidden = true)
    @TableField(exist = false)
    private List<DapDataModelTableField> indexFields;
    @ApiModelProperty(value = "用于数据对比中多版本的关联键值", hidden = true)
    @TableField(exist = false)
    private String bmKey;

    @ApiModelProperty(value = "数据库类型，用于区分不同数据库，equals中mysql忽略大小写判断相等", hidden = true)
    @TableField(exist = false)
    private DatabaseType dbType;

    public DapDataModelSubordinateKey() {
        this.dbType = DatabaseType.MYSQL;
    }

    public DapDataModelSubordinateKey(DatabaseType dbType) {
        this.dbType = dbType;
    }

    /**
     * 获取字段id
     *
     * @return 获取字段id
     */
    public String[] getFieldIdsSplit() {
        if (getFieldIds() == null) {
            return new String[0];
        }
        return getFieldIds().split(INDEX_FIELDIDS_CHAR);
    }

    public String[] getFieldNamesSplit() {
        if (getFieldNames() == null) {
            return new String[0];
        }
        return getFieldNames().split(INDEX_FIELDIDS_CHAR);
    }

    public String[] fieldNameSubPartsArr(){
        if (getFieldNameSubParts() == null) {
            return new String[0];
        }
        return getFieldNameSubParts().split(INDEX_FIELDIDS_CHAR);

    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DapDataModelSubordinateKey that = (DapDataModelSubordinateKey) o;
        if (DatabaseType.MYSQL.equals(dbType)) {
            return Objects.equal(keyChinName, that.keyChinName) &&
                    Objects.equal(keyMethod, that.keyMethod) &&
                    StringUtils.equalsIgnoreCase(keyName, that.keyName) &&
                    Objects.equal(keyType, that.keyType) &&
                    StringUtils.equalsIgnoreCase(fieldNames, that.fieldNames) &&
                    StringUtils.equalsIgnoreCase(tableName, that.tableName);
        }
        return Objects.equal(keyChinName, that.keyChinName) &&
                Objects.equal(keyMethod, that.keyMethod) &&
                Objects.equal(keyName, that.keyName) &&
                Objects.equal(keyType, that.keyType) &&
                Objects.equal(fieldNames, that.fieldNames) &&
                Objects.equal(tableName, that.tableName);
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(keyChinName, keyMethod, keyName, keyType, fieldNames, tableName);
    }

    @Override
    public String[] sqlCompareFields() {
        return includeFields;
    }
}
